home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ELYVER10.ZIP / MIKXMAS.ZIP / source / mplayer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-12  |  29.5 KB  |  1,387 lines

  1. /*
  2.  
  3. Name:
  4. MPLAYER.C
  5.  
  6. Description:
  7. The actual modplaying routines
  8.  
  9. Portability:
  10. All systems - all compilers
  11.  
  12. */
  13. #include <stdlib.h>
  14. #include "mikmod.h"
  15.  
  16. UNIMOD *pf;                     /* <- this modfile is being played */
  17. UWORD reppos;                   /* patternloop position */
  18. UWORD repcnt;                   /* times to loop */
  19. UWORD vbtick;                   /* tick counter */
  20. UWORD patbrk;                   /* position where to start a new pattern */
  21. UBYTE patdly;                   /* patterndelay counter */
  22. UBYTE patdly2;                  /* patterndelay counter */
  23. UWORD numrow;                   /* number of rows on current pattern */
  24. SWORD  posjmp;                   /*      flag to indicate a position jump is needed...
  25.                             changed since 1.00: now also indicates the
  26.                             direction the position has to jump to:
  27.  
  28.                             0: Don't do anything
  29.                             1: Jump back 1 position
  30.                             2: Restart on current position
  31.                             3: Jump forward 1 position
  32.                         */
  33. int   forbid;                   /* forbidflag */
  34. static int isfirst;
  35.  
  36. /*
  37.     Set forbid to 1 when you want to modify any of the mp_sngpos, mp_patpos etc.
  38.     variables and clear it when you're done. This prevents getting strange
  39.     results due to intermediate interrupts.
  40. */
  41.  
  42.  
  43. AUDTMP mp_audio[32];    /* max 32 channels */
  44. UBYTE  mp_bpm;          /* beats-per-minute speed */
  45. UWORD  mp_patpos;       /* current row number (0-255) */
  46. SWORD  mp_sngpos;       /* current song position */
  47. UWORD  mp_sngspd;       /* current songspeed */
  48. UWORD  mp_channel;      /* channel it's working on */
  49. BOOL   mp_extspd=1;     /* extended speed flag, default enabled */
  50. BOOL   mp_panning=1;    /* panning flag, default enabled */
  51. BOOL   mp_loop=0;       /* loop module ? */
  52. UBYTE  mp_volume=100;   /* song volume (0-100) (or user volume) */
  53.  
  54. static SBYTE globalvolume=64;    /* global volume */
  55. static UBYTE globalslide;
  56.  
  57. AUDTMP *a;                              /* current AUDTMP it's working on */
  58.  
  59.  
  60. UWORD mytab[12]={
  61.     1712*16,1616*16,1524*16,1440*16,1356*16,1280*16,
  62.     1208*16,1140*16,1076*16,1016*16,960*16,907*16
  63. };
  64.  
  65. static UBYTE VibratoTable[32]={
  66.     0,24,49,74,97,120,141,161,
  67.     180,197,212,224,235,244,250,253,
  68.     255,253,250,244,235,224,212,197,
  69.     180,161,141,120,97,74,49,24
  70. };
  71.  
  72.  
  73. /* linear periods to frequency translation table: */
  74.  
  75. UWORD lintab[768]={
  76. 16726,16741,16756,16771,16786,16801,16816,16832,16847,16862,16877,16892,16908,16923,16938,16953,
  77. 16969,16984,16999,17015,17030,17046,17061,17076,17092,17107,17123,17138,17154,17169,17185,17200,
  78. 17216,17231,17247,17262,17278,17293,17309,17325,17340,17356,17372,17387,17403,17419,17435,17450,
  79. 17466,17482,17498,17513,17529,17545,17561,17577,17593,17608,17624,17640,17656,17672,17688,17704,
  80. 17720,17736,17752,17768,17784,17800,17816,17832,17848,17865,17881,17897,17913,17929,17945,17962,
  81. 17978,17994,18010,18027,18043,18059,18075,18092,18108,18124,18141,18157,18174,18190,18206,18223,
  82. 18239,18256,18272,18289,18305,18322,18338,18355,18372,18388,18405,18421,18438,18455,18471,18488,
  83. 18505,18521,18538,18555,18572,18588,18605,18622,18639,18656,18672,18689,18706,18723,18740,18757,
  84. 18774,18791,18808,18825,18842,18859,18876,18893,18910,18927,18944,18961,18978,18995,19013,19030,
  85. 19047,19064,19081,19099,19116,19133,19150,19168,19185,19202,19220,19237,19254,19272,19289,19306,
  86. 19324,19341,19359,19376,19394,19411,19429,19446,19464,19482,19499,19517,19534,19552,19570,19587,
  87. 19605,19623,19640,19658,19676,19694,19711,19729,19747,19765,19783,19801,19819,19836,19854,19872,
  88. 19890,19908,19926,19944,19962,19980,19998,20016,20034,20052,20071,20089,20107,20125,20143,20161,
  89. 20179,20198,20216,20234,20252,20271,20289,20307,20326,20344,20362,20381,20399,20418,20436,20455,
  90. 20473,20492,20510,20529,20547,20566,20584,20603,20621,20640,20659,20677,20696,20715,20733,20752,
  91. 20771,20790,20808,20827,20846,20865,20884,20902,20921,20940,20959,20978,20997,21016,21035,21054,
  92. 21073,21092,21111,21130,21149,21168,21187,21206,21226,21245,21264,21283,21302,21322,21341,21360,
  93. 21379,21399,21418,21437,21457,21476,21496,21515,21534,21554,21573,21593,21612,21632,21651,21671,
  94. 21690,21710,21730,21749,21769,21789,21808,21828,21848,21867,21887,21907,21927,21946,21966,21986,
  95. 22006,22026,22046,22066,22086,22105,22125,22145,22165,22185,22205,22226,22246,22266,22286,22306,
  96. 22326,22346,22366,22387,22407,22427,22447,22468,22488,22508,22528,22549,22569,22590,22610,22630,
  97. 22651,22671,22692,22712,22733,22753,22774,22794,22815,22836,22856,22877,22897,22918,22939,22960,
  98. 22980,23001,23022,23043,23063,23084,23105,23126,23147,23168,23189,23210,23230,23251,23272,23293,
  99. 23315,23336,23357,23378,23399,23420,23441,23462,23483,23505,23526,23547,23568,23590,23611,23632,
  100. 23654,23675,23696,23718,23739,23761,23782,23804,23825,23847,23868,23890,23911,23933,23954,23976,
  101. 23998,24019,24041,24063,24084,24106,24128,24150,24172,24193,24215,24237,24259,24281,24303,24325,
  102. 24347,24369,24391,24413,24435,24457,24479,24501,24523,24545,24567,24590,24612,24634,24656,24679,
  103. 24701,24723,24746,24768,24790,24813,24835,24857,24880,24902,24925,24947,24970,24992,25015,25038,
  104. 25060,25083,25105,25128,25151,25174,25196,25219,25242,25265,25287,25310,25333,25356,25379,25402,
  105. 25425,25448,25471,25494,25517,25540,25563,25586,25609,25632,25655,25678,25702,25725,25748,25771,
  106. 25795,25818,25841,25864,25888,25911,25935,25958,25981,26005,26028,26052,26075,26099,26123,26146,
  107. 26170,26193,26217,26241,26264,26288,26312,26336,26359,26383,26407,26431,26455,26479,26502,26526,
  108. 26550,26574,26598,26622,26646,26670,26695,26719,26743,26767,26791,26815,26839,26864,26888,26912,
  109. 26937,26961,26985,27010,27034,27058,27083,27107,27132,27156,27181,27205,27230,27254,27279,27304,
  110. 27328,27353,27378,27402,27427,27452,27477,27502,27526,27551,27576,27601,27626,27651,27676,27701,
  111. 27726,27751,27776,27801,27826,27851,27876,27902,27927,27952,27977,28003,28028,28053,28078,28104,
  112. 28129,28155,28180,28205,28231,28256,28282,28307,28333,28359,28384,28410,28435,28461,28487,28513,
  113. 28538,28564,28590,28616,28642,28667,28693,28719,28745,28771,28797,28823,28849,28875,28901,28927,
  114. 28953,28980,29006,29032,29058,29084,29111,29137,29163,29190,29216,29242,29269,29295,29322,29348,
  115. 29375,29401,29428,29454,29481,29507,29534,29561,29587,29614,29641,29668,29694,29721,29748,29775,
  116. 29802,29829,29856,29883,29910,29937,29964,29991,30018,30045,30072,30099,30126,30154,30181,30208,
  117. 30235,30263,30290,30317,30345,30372,30400,30427,30454,30482,30509,30537,30565,30592,30620,30647,
  118. 30675,30703,30731,30758,30786,30814,30842,30870,30897,30925,30953,30981,31009,31037,31065,31093,
  119. 31121,31149,31178,31206,31234,31262,31290,31319,31347,31375,31403,31432,31460,31489,31517,31546,
  120. 31574,31602,31631,31660,31688,31717,31745,31774,31803,31832,31860,31889,31918,31947,31975,32004,
  121. 32033,32062,32091,32120,32149,32178,32207,32236,32265,32295,32324,32353,32382,32411,32441,32470,
  122. 32499,32529,32558,32587,32617,32646,32676,32705,32735,32764,32794,32823,32853,32883,32912,32942,
  123. 32972,33002,33031,33061,33091,33121,33151,33181,33211,33241,33271,33301,33331,33361,33391,33421
  124. };
  125.  
  126.  
  127.  
  128.  
  129. #define LOGFAC 2*16
  130.  
  131. UWORD logtab[]={
  132.     LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887,LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862,
  133.     LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838,LOGFAC*832,LOGFAC*826,LOGFAC*820,LOGFAC*814,
  134.     LOGFAC*808,LOGFAC*802,LOGFAC*796,LOGFAC*791,LOGFAC*785,LOGFAC*779,LOGFAC*774,LOGFAC*768,
  135.     LOGFAC*762,LOGFAC*757,LOGFAC*752,LOGFAC*746,LOGFAC*741,LOGFAC*736,LOGFAC*730,LOGFAC*725,
  136.     LOGFAC*720,LOGFAC*715,LOGFAC*709,LOGFAC*704,LOGFAC*699,LOGFAC*694,LOGFAC*689,LOGFAC*684,
  137.     LOGFAC*678,LOGFAC*675,LOGFAC*670,LOGFAC*665,LOGFAC*660,LOGFAC*655,LOGFAC*651,LOGFAC*646,
  138.     LOGFAC*640,LOGFAC*636,LOGFAC*632,LOGFAC*628,LOGFAC*623,LOGFAC*619,LOGFAC*614,LOGFAC*610,
  139.     LOGFAC*604,LOGFAC*601,LOGFAC*597,LOGFAC*592,LOGFAC*588,LOGFAC*584,LOGFAC*580,LOGFAC*575,
  140.     LOGFAC*570,LOGFAC*567,LOGFAC*563,LOGFAC*559,LOGFAC*555,LOGFAC*551,LOGFAC*547,LOGFAC*543,
  141.     LOGFAC*538,LOGFAC*535,LOGFAC*532,LOGFAC*528,LOGFAC*524,LOGFAC*520,LOGFAC*516,LOGFAC*513,
  142.     LOGFAC*508,LOGFAC*505,LOGFAC*502,LOGFAC*498,LOGFAC*494,LOGFAC*491,LOGFAC*487,LOGFAC*484,
  143.     LOGFAC*480,LOGFAC*477,LOGFAC*474,LOGFAC*470,LOGFAC*467,LOGFAC*463,LOGFAC*460,LOGFAC*457,
  144.     LOGFAC*453,LOGFAC*450,LOGFAC*447,LOGFAC*443,LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431
  145. };
  146.  
  147.  
  148. SWORD Interpolate(SWORD p,SWORD p1,SWORD p2,SWORD v1,SWORD v2)
  149. {
  150.     SWORD dp,dv,di;
  151.  
  152.     if(p1==p2) return v1;
  153.  
  154.     dv=v2-v1;
  155.     dp=p2-p1;
  156.     di=p-p1;
  157.  
  158.     return v1 + ((SLONG)(di*dv) / dp);
  159. }
  160.  
  161.  
  162. UWORD getlinearperiod(UBYTE note,UWORD fine)
  163. {
  164.     return((10L*12*16*4)-((UWORD)note*16*4)-(fine/2)+64);
  165. }
  166.  
  167.  
  168. UWORD getlogperiod(UBYTE note,UWORD fine)
  169. {
  170.     UBYTE n,o;
  171.     UWORD p1,p2,i;
  172.  
  173.     n=note%12;
  174.     o=note/12;
  175.     i=(n<<3)+(fine>>4);                     /* n*8 + fine/16 */
  176.  
  177.     p1=logtab[i];
  178.     p2=logtab[i+1];
  179.  
  180.     return(Interpolate(fine/16,0,15,p1,p2)>>o);
  181. }
  182.  
  183.  
  184. UWORD getoldperiod(UBYTE note,UWORD c2spd)
  185. {
  186.     UBYTE n,o;
  187.     ULONG period;
  188.  
  189.     if(!c2spd) return 4242;         /* <- prevent divide overflow.. (42 eheh) */
  190.  
  191.     n=note%12;
  192.     o=note/12;
  193.     period=((8363L*mytab[n]) >> o )/c2spd;
  194.     return period;
  195. }
  196.  
  197.  
  198.  
  199. UWORD GetPeriod(UBYTE note,UWORD c2spd)
  200. {
  201.     if(pf->flags&UF_XMPERIODS){
  202.         return (pf->flags&UF_LINEAR) ? getlinearperiod(note,c2spd) : getlogperiod(note,c2spd);
  203.     }
  204.     return(getoldperiod(note,c2spd));
  205. }
  206.  
  207.  
  208.  
  209. void DoEEffects(UBYTE dat)
  210. {
  211.     UBYTE nib;
  212.  
  213.     nib=dat&0xf;
  214.  
  215.     switch(dat>>4){
  216.  
  217.         case 0x0:       /* filter toggle, not supported */
  218.                 break;
  219.  
  220.         case 0x1:       /* fineslide up */
  221.                 if(!vbtick) a->tmpperiod-=(nib<<2);
  222.                 break;
  223.  
  224.         case 0x2:       /* fineslide dn */
  225.                 if(!vbtick) a->tmpperiod+=(nib<<2);
  226.                 break;
  227.  
  228.         case 0x3:       /* glissando ctrl */
  229.                 a->glissando=nib;
  230.                 break;
  231.  
  232.         case 0x4:       /* set vibrato waveform */
  233.                 a->wavecontrol&=0xf0;
  234.                 a->wavecontrol|=nib;
  235.                 break;
  236.  
  237.         case 0x5:       /* set finetune */
  238. /*                              a->c2spd=finetune[nib]; */
  239. /*                              a->tmpperiod=GetPeriod(a->note,pf->samples[a->sample].transpose,a->c2spd); */
  240.                 break;
  241.  
  242.         case 0x6:       /* set patternloop */
  243.  
  244.                 if(vbtick) break;
  245.  
  246.                 /* hmm.. this one is a real kludge. But now it
  247.                    works. */
  248.  
  249.                 if(nib){                /* set reppos or repcnt ? */
  250.  
  251.                     /* set repcnt, so check if repcnt already is set,
  252.                        which means we are already looping */
  253.  
  254.                     if(repcnt>0)
  255.                         repcnt--;               /* already looping, decrease counter */
  256.                     else
  257.                         repcnt=nib;             /* not yet looping, so set repcnt */
  258.  
  259.                     if(repcnt)                      /* jump to reppos if repcnt>0 */
  260.                         mp_patpos=reppos;
  261.                 }
  262.                 else{
  263.                     reppos=mp_patpos-1;     /* set reppos */
  264.                 }
  265.                 break;
  266.  
  267.  
  268.         case 0x7:       /* set tremolo waveform */
  269.                 a->wavecontrol&=0x0f;
  270.                 a->wavecontrol|=nib<<4;
  271.                 break;
  272.  
  273.                 case 0x8:       /* set panning */
  274.                                 if(mp_panning){
  275.                                         nib<<=4;
  276.                                         a->panning=nib;
  277.                                         pf->panning[mp_channel]=nib;
  278.                                 }
  279.                 break;
  280.  
  281.         case 0x9:       /* retrig note */
  282.  
  283.                 /* only retrigger if
  284.                    data nibble > 0 */
  285.  
  286.                 if(nib>0){
  287.                     if(a->retrig==0){
  288.  
  289.                         /* when retrig counter reaches 0,
  290.                            reset counter and restart the sample */
  291.  
  292.                         a->kick=1;
  293.                         a->retrig=nib;
  294.                     }
  295.                     a->retrig--; /* countdown */
  296.                 }
  297.                 break;
  298.  
  299.         case 0xa:       /* fine volume slide up */
  300.                 if(vbtick) break;
  301.  
  302.                 a->tmpvolume+=nib;
  303.                 if(a->tmpvolume>64) a->tmpvolume=64;
  304.                 break;
  305.  
  306.         case 0xb:       /* fine volume slide dn */
  307.                 if(vbtick) break;
  308.  
  309.                 a->tmpvolume-=nib;
  310.                 if(a->tmpvolume<0) a->tmpvolume=0;
  311.                 break;
  312.  
  313.         case 0xc:       /* cut note */
  314.  
  315.                 /* When vbtick reaches the cut-note value,
  316.                    turn the volume to zero ( Just like
  317.                    on the amiga) */
  318.  
  319.                 if(vbtick>=nib){
  320.                     a->tmpvolume=0;                 /* just turn the volume down */
  321.                 }
  322.                 break;
  323.  
  324.         case 0xd:       /* note delay */
  325.  
  326.                 /* delay the start of the
  327.                    sample until vbtick==nib */
  328.  
  329.                 if(vbtick==nib){
  330.                     a->kick=1;
  331.                 }
  332.                 else a->kick=0;
  333.                 break;
  334.  
  335.         case 0xe:       /* pattern delay */
  336.                 if(vbtick) break;
  337.                 if(!patdly2) patdly=nib+1;                              /* only once (when vbtick=0) */
  338.                 break;
  339.  
  340.         case 0xf:       /* invert loop, not supported */
  341.                 break;
  342.     }
  343. }
  344.  
  345.  
  346. void DoVibrato(void)
  347. {
  348.     UBYTE q;
  349.     UWORD temp;
  350.  
  351.     q=(a->vibpos>>2)&0x1f;
  352.  
  353.     switch(a->wavecontrol&3){
  354.  
  355.         case 0: /* sine */
  356.             temp=VibratoTable[q];
  357.             break;
  358.  
  359.         case 1: /* ramp down */
  360.             q<<=3;
  361.             if(a->vibpos<0) q=255-q;
  362.             temp=q;
  363.             break;
  364.  
  365.         case 2: /* square wave */
  366.             temp=255;
  367.             break;
  368.     }
  369.  
  370.     temp*=a->vibdepth;
  371.     temp>>=7;
  372.     temp<<=2;
  373.  
  374.     if(a->vibpos>=0)
  375.         a->period=a->tmpperiod+temp;
  376.     else
  377.         a->period=a->tmpperiod-temp;
  378.  
  379.     if(vbtick) a->vibpos+=a->vibspd;        /* do not update when vbtick==0 */
  380. }
  381.  
  382.  
  383.  
  384. void DoTremolo(void)
  385. {
  386.     UBYTE q;
  387.     UWORD temp;
  388.  
  389.     q=(a->trmpos>>2)&0x1f;
  390.  
  391.     switch((a->wavecontrol>>4)&3){
  392.  
  393.         case 0: /* sine */
  394.             temp=VibratoTable[q];
  395.             break;
  396.  
  397.         case 1: /* ramp down */
  398.             q<<=3;
  399.             if(a->trmpos<0) q=255-q;
  400.             temp=q;
  401.             break;
  402.  
  403.         case 2: /* square wave */
  404.             temp=255;
  405.             break;
  406.     }
  407.  
  408.     temp*=a->trmdepth;
  409.     temp>>=6;
  410.  
  411.     if(a->trmpos>=0){
  412.         a->volume=a->tmpvolume+temp;
  413.         if(a->volume>64) a->volume=64;
  414.     }
  415.     else{
  416.         a->volume=a->tmpvolume-temp;
  417.         if(a->volume<0) a->volume=0;
  418.     }
  419.  
  420.     if(vbtick) a->trmpos+=a->trmspd;        /* do not update when vbtick==0 */
  421. }
  422.  
  423.  
  424. void DoVolSlide(UBYTE dat)
  425. {
  426.     if(!vbtick) return;             /* do not update when vbtick==0 */
  427.  
  428.     a->tmpvolume+=dat>>4;           /* volume slide */
  429.     a->tmpvolume-=dat&0xf;
  430.     if(a->tmpvolume<0) a->tmpvolume=0;
  431.     if(a->tmpvolume>64) a->tmpvolume=64;
  432. }
  433.  
  434.  
  435.  
  436. void DoS3MVolSlide(UBYTE inf)
  437. {
  438.     UBYTE lo,hi;
  439.  
  440.     if(inf){
  441.         a->s3mvolslide=inf;
  442.     }
  443.     inf=a->s3mvolslide;
  444.  
  445.     lo=inf&0xf;
  446.     hi=inf>>4;
  447.  
  448.     if(hi==0){
  449.         a->tmpvolume-=lo;
  450.     }
  451.     else if(lo==0){
  452.         a->tmpvolume+=hi;
  453.     }
  454.     else if(hi==0xf){
  455.         if(!vbtick) a->tmpvolume-=lo;
  456.     }
  457.     else if(lo==0xf){
  458.         if(!vbtick) a->tmpvolume+=hi;
  459.     }
  460.  
  461.     if(a->tmpvolume<0) a->tmpvolume=0;
  462.     if(a->tmpvolume>64) a->tmpvolume=64;
  463. }
  464.  
  465.  
  466.  
  467. void DoXMVolSlide(UBYTE inf)
  468. {
  469.     UBYTE lo,hi;
  470.  
  471.     if(inf){
  472.         a->s3mvolslide=inf;
  473.     }
  474.     inf=a->s3mvolslide;
  475.  
  476.     if(!vbtick) return;
  477.  
  478.     lo=inf&0xf;
  479.     hi=inf>>4;
  480.  
  481.     if(hi==0)
  482.         a->tmpvolume-=lo;
  483.     else
  484.         a->tmpvolume+=hi;
  485.  
  486.     if(a->tmpvolume<0) a->tmpvolume=0;
  487.     else if(a->tmpvolume>64) a->tmpvolume=64;
  488. }
  489.  
  490.  
  491.  
  492. void DoXMGlobalSlide(UBYTE inf)
  493. {
  494.     UBYTE lo,hi;
  495.  
  496.     if(inf){
  497.         globalslide=inf;
  498.     }
  499.     inf=globalslide;
  500.  
  501.     if(!vbtick) return;
  502.  
  503.     lo=inf&0xf;
  504.     hi=inf>>4;
  505.  
  506.     if(hi==0)
  507.         globalvolume-=lo;
  508.     else
  509.         globalvolume+=hi;
  510.  
  511.     if(globalvolume<0) globalvolume=0;
  512.     else if(globalvolume>64) globalvolume=64;
  513. }
  514.  
  515.  
  516.  
  517. void DoXMPanSlide(UBYTE inf)
  518. {
  519.     UBYTE lo,hi;
  520.     SWORD pan;
  521.  
  522.  
  523.     if(inf!=0) a->pansspd=inf;
  524.     else inf=a->pansspd;
  525.  
  526.     if(!vbtick) return;
  527.  
  528.     lo=inf&0xf;
  529.     hi=inf>>4;
  530.  
  531.     /* slide right has absolute priority: */
  532.  
  533.     if(hi) lo=0;
  534.  
  535.     pan=a->panning;
  536.  
  537.     pan-=lo;
  538.     pan+=hi;
  539.  
  540.     if(pan<0) pan=0;
  541.     if(pan>255) pan=255;
  542.  
  543.     a->panning=pan;
  544. }
  545.  
  546.  
  547.  
  548. void DoS3MSlideDn(UBYTE inf)
  549. {
  550.     UBYTE hi,lo;
  551.  
  552.     if(inf!=0) a->slidespeed=inf;
  553.     else inf=a->slidespeed;
  554.  
  555.     hi=inf>>4;
  556.     lo=inf&0xf;
  557.  
  558.     if(hi==0xf){
  559.         if(!vbtick) a->tmpperiod+=(UWORD)lo<<2;
  560.     }
  561.     else if(hi==0xe){
  562.         if(!vbtick) a->tmpperiod+=lo;
  563.     }
  564.     else{
  565.         if(vbtick) a->tmpperiod+=(UWORD)inf<<2;
  566.     }
  567. }
  568.  
  569.  
  570.  
  571. void DoS3MSlideUp(UBYTE inf)
  572. {
  573.     UBYTE hi,lo;
  574.  
  575.     if(inf!=0) a->slidespeed=inf;
  576.     else inf=a->slidespeed;
  577.  
  578.     hi=inf>>4;
  579.     lo=inf&0xf;
  580.  
  581.     if(hi==0xf){
  582.         if(!vbtick) a->tmpperiod-=(UWORD)lo<<2;
  583.     }
  584.     else if(hi==0xe){
  585.         if(!vbtick) a->tmpperiod-=lo;
  586.     }
  587.     else{
  588.         if(vbtick) a->tmpperiod-=(UWORD)inf<<2;
  589.     }
  590. }
  591.  
  592.  
  593.  
  594. void DoS3MTremor(UBYTE inf)
  595. {
  596.     UBYTE on,off;
  597.  
  598.     if(inf!=0) a->s3mtronof=inf;
  599.     else inf=a->s3mtronof;
  600.  
  601.     if(!vbtick) return;
  602.  
  603.     on=(inf>>4)+1;
  604.     off=(inf&0xf)+1;
  605.  
  606.     a->s3mtremor%=(on+off);
  607.     a->volume=(a->s3mtremor < on ) ? a->tmpvolume:0;
  608.     a->s3mtremor++;
  609. }
  610.  
  611.  
  612.  
  613. void DoS3MRetrig(UBYTE inf)
  614. {
  615.     UBYTE hi,lo;
  616.  
  617.     hi=inf>>4;
  618.     lo=inf&0xf;
  619.  
  620.     if(lo){
  621.         a->s3mrtgslide=hi;
  622.         a->s3mrtgspeed=lo;
  623.     }
  624.  
  625.     if(hi){
  626.         a->s3mrtgslide=hi;
  627.     }
  628.  
  629.     /* only retrigger if
  630.        lo nibble > 0 */
  631.  
  632.     if(a->s3mrtgspeed>0){
  633.         if(a->retrig==0){
  634.  
  635.             /* when retrig counter reaches 0,
  636.                reset counter and restart the sample */
  637.  
  638.             a->kick=1;
  639.             a->retrig=a->s3mrtgspeed;
  640.  
  641.             if(vbtick){                     /* don't slide on first retrig */
  642.                 switch(a->s3mrtgslide){
  643.  
  644.                     case 1:
  645.                     case 2:
  646.                     case 3:
  647.                     case 4:
  648.                     case 5:
  649.                         a->tmpvolume-=(1<<(a->s3mrtgslide-1));
  650.                         break;
  651.  
  652.                     case 6:
  653.                         a->tmpvolume=(2*a->tmpvolume)/3;
  654.                         break;
  655.  
  656.                     case 7:
  657.                         a->tmpvolume=a->tmpvolume>>1;
  658.                         break;
  659.  
  660.                     case 9:
  661.                     case 0xa:
  662.                     case 0xb:
  663.                     case 0xc:
  664.                     case 0xd:
  665.                         a->tmpvolume+=(1<<(a->s3mrtgslide-9));
  666.                         break;
  667.  
  668.                     case 0xe:
  669.                         a->tmpvolume=(3*a->tmpvolume)/2;
  670.                         break;
  671.  
  672.                     case 0xf:
  673.                         a->tmpvolume=a->tmpvolume<<1;
  674.                         break;
  675.                 }
  676.                 if(a->tmpvolume<0) a->tmpvolume=0;
  677.                 if(a->tmpvolume>64) a->tmpvolume=64;
  678.             }
  679.         }
  680.         a->retrig--; /* countdown */
  681.     }
  682. }
  683.  
  684.  
  685. void DoS3MSpeed(UBYTE speed)
  686. {
  687.     if(vbtick || patdly2) return;
  688.  
  689.     if(speed){                      /* <- v0.44 bugfix */
  690.         mp_sngspd=speed;
  691.         vbtick=0;
  692.     }
  693. }
  694.  
  695.  
  696. void DoS3MTempo(UBYTE tempo)
  697. {
  698.     if(vbtick || patdly2) return;
  699.     mp_bpm=tempo;
  700. }
  701.  
  702.  
  703. void DoToneSlide(void)
  704. {
  705.     int dist,t;
  706.  
  707.     if(!vbtick){
  708.         a->tmpperiod=a->period;
  709.         return;
  710.     }
  711.  
  712.     /* We have to slide a->period towards a->wantedperiod, so
  713.        compute the difference between those two values */
  714.  
  715.     dist=a->period-a->wantedperiod;
  716.  
  717.     if( dist==0 ||                          /* if they are equal */
  718.         a->portspeed>abs(dist) ){       /* or if portamentospeed is too big */
  719.  
  720.         a->period=a->wantedperiod;      /* make tmpperiod equal tperiod */
  721.     }
  722.     else if(dist>0){                                /* dist>0 ? */
  723.         a->period-=a->portspeed;        /* then slide up */
  724.     }
  725.     else
  726.         a->period+=a->portspeed;        /* dist<0 -> slide down */
  727.  
  728. /*      if(a->glissando){
  729.  
  730.          If glissando is on, find the nearest
  731.            halfnote to a->tmpperiod
  732.  
  733.         for(t=0;t<60;t++){
  734.             if(a->tmpperiod>=npertab[a->finetune][t]) break;
  735.         }
  736.  
  737.         a->period=npertab[a->finetune][t];
  738.     }
  739.     else
  740. */
  741.     a->tmpperiod=a->period;
  742. }
  743.  
  744.  
  745. void DoPTEffect0(UBYTE dat)
  746. {
  747.     UBYTE note;
  748.  
  749.     note=a->note;
  750.  
  751.     if(dat!=0){
  752.         switch(vbtick%3){
  753.             case 1:
  754.                 note+=(dat>>4); break;
  755.             case 2:
  756.                 note+=(dat&0xf); break;
  757.         }
  758.         a->period=GetPeriod(note+a->transpose,a->c2spd);
  759.         a->ownper=1;
  760.     }
  761. }
  762.  
  763.  
  764. void PlayNote(void)
  765. {
  766.     INSTRUMENT *i;
  767.     SAMPLE *s;
  768.     UWORD period;
  769.     UBYTE inst,c;
  770.     UBYTE note;
  771.  
  772.     if(a->row==NULL) return;
  773.  
  774.     UniSetRow(a->row);
  775.  
  776.     while(c=UniGetByte()){
  777.  
  778.         switch(c){
  779.  
  780.             case UNI_NOTE:
  781.                 note=UniGetByte();
  782.  
  783.                 if(note==96){                   /* key off ? */
  784.                     a->keyon=0;
  785.                     if(a->i && !(a->i->volflg & EF_ON)){
  786.                         a->tmpvolume=0;
  787.                     }
  788.                 }
  789.                 else{
  790.                     a->note=note;
  791.  
  792.                     period=GetPeriod(note+a->transpose,a->c2spd);
  793.  
  794.                     a->wantedperiod=period;
  795.                     a->tmpperiod=period;
  796.  
  797.                     a->kick=1;
  798.                     a->start=0;
  799.  
  800.                     /* retrig tremolo and vibrato waves ? */
  801.  
  802.                     if(!(a->wavecontrol&0x80)) a->trmpos=0;
  803.                     if(!(a->wavecontrol&0x08)) a->vibpos=0;
  804.                 }
  805.                 break;
  806.  
  807.             case UNI_INSTRUMENT:
  808.                 inst=UniGetByte();
  809.                 if(inst>=pf->numins) break;             /* <- safety valve */
  810.  
  811.                 a->sample=inst;
  812.  
  813.                 i=&pf->instruments[inst];
  814.                 a->i=i;
  815.  
  816.                 if(i->samplenumber[a->note]>=i->numsmp) break;
  817.  
  818.                 s=&i->samples[i->samplenumber[a->note]];
  819.                 a->s=s;
  820.  
  821.                 /* channel or instrument determined panning ? */
  822.  
  823.                 if(s->flags& SF_OWNPAN){
  824.                     a->panning=s->panning;
  825.                 }
  826.                 else{
  827.                     a->panning=pf->panning[mp_channel];
  828.                 }
  829.  
  830.                 a->transpose=s->transpose;
  831.                 a->handle=s->handle;
  832.                 a->tmpvolume=s->volume;
  833.                 a->volume=s->volume;
  834.                 a->c2spd=s->c2spd;
  835.                 a->retrig=0;
  836.                 a->s3mtremor=0;
  837.  
  838.                 period=GetPeriod(a->note+a->transpose,a->c2spd);
  839.  
  840.                 a->wantedperiod=period;
  841.                 a->tmpperiod=period;
  842.                 break;
  843.  
  844.             default:
  845.                 UniSkipOpcode(c);
  846.                 break;
  847.         }
  848.     }
  849. }
  850.  
  851.  
  852.  
  853.  
  854. void PlayEffects(void)
  855. {
  856.     UBYTE c,dat;
  857.  
  858.     if(a->row==NULL) return;
  859.  
  860.     UniSetRow(a->row);
  861.  
  862.     a->ownper=0;
  863.     a->ownvol=0;
  864.  
  865.     while(c=UniGetByte()){
  866.  
  867.         switch(c){
  868.  
  869.             case UNI_NOTE:
  870.             case UNI_INSTRUMENT:
  871.                 UniSkipOpcode(c);
  872.                 break;
  873.  
  874.             case UNI_PTEFFECT0:
  875.                 DoPTEffect0(UniGetByte());
  876.                 break;
  877.  
  878.             case UNI_PTEFFECT1:
  879.                 dat=UniGetByte();
  880.                 if(dat!=0) a->slidespeed=(UWORD)dat<<2;
  881.                 if(vbtick) a->tmpperiod-=a->slidespeed;
  882.                 break;
  883.  
  884.             case UNI_PTEFFECT2:
  885.                 dat=UniGetByte();
  886.                 if(dat!=0) a->slidespeed=(UWORD)dat<<2;
  887.                 if(vbtick) a->tmpperiod+=a->slidespeed;
  888.                 break;
  889.  
  890.             case UNI_PTEFFECT3:
  891.                 dat=UniGetByte();
  892.                 a->kick=0;                              /* temp XM fix */
  893.                 if(dat!=0){
  894.                     a->portspeed=dat;
  895.                     a->portspeed<<=2;
  896.                 }
  897.                 DoToneSlide();
  898.                 a->ownper=1;
  899.                 break;
  900.  
  901.             case UNI_PTEFFECT4:
  902.                 dat=UniGetByte();
  903.                 if(dat&0x0f) a->vibdepth=dat&0xf;
  904.                 if(dat&0xf0) a->vibspd=(dat&0xf0)>>2;
  905.                 DoVibrato();
  906.                 a->ownper=1;
  907.                 break;
  908.  
  909.             case UNI_PTEFFECT5:
  910.                 dat=UniGetByte();
  911.                 a->kick=0;
  912.                 DoToneSlide();
  913.                 DoVolSlide(dat);
  914.                 a->ownper=1;
  915.                 break;
  916.  
  917.             case UNI_PTEFFECT6:
  918.                 dat=UniGetByte();
  919.                 DoVibrato();
  920.                 DoVolSlide(dat);
  921.                 a->ownper=1;
  922.                 break;
  923.  
  924.             case UNI_PTEFFECT7:
  925.                 dat=UniGetByte();
  926.                 if(dat&0x0f) a->trmdepth=dat&0xf;
  927.                 if(dat&0xf0) a->trmspd=(dat&0xf0)>>2;
  928.                 DoTremolo();
  929.                 a->ownvol=1;
  930.                 break;
  931.  
  932.             case UNI_PTEFFECT8:
  933.                 dat=UniGetByte();
  934.                                 if(mp_panning){
  935.                                         a->panning=dat;
  936.                                         pf->panning[mp_channel]=dat;
  937.                                 }
  938.                 break;
  939.  
  940.             case UNI_PTEFFECT9:
  941.                 dat=UniGetByte();
  942.                 if(dat) a->soffset=(UWORD)dat<<8;       /* <- 0.43 fix.. */
  943.                 a->start=a->soffset;
  944.                 if(a->start>a->s->length) a->start=a->s->length;
  945.                 break;
  946.  
  947.             case UNI_PTEFFECTA:
  948.                 DoVolSlide(UniGetByte());
  949.                 break;
  950.  
  951.             case UNI_PTEFFECTB:
  952.                 dat=UniGetByte();
  953.                 if(patdly2) break;
  954.                 patbrk=0;
  955.                 mp_sngpos=dat-1;
  956.                 posjmp=3;
  957.                 break;
  958.  
  959.             case UNI_PTEFFECTC:
  960.                 dat=UniGetByte();
  961.                 if(vbtick) break;
  962.                 if(dat>64) dat=64;
  963.                 a->tmpvolume=dat;
  964.                 break;
  965.  
  966.             case UNI_PTEFFECTD:
  967.                 dat=UniGetByte();
  968.                 if(patdly2) break;
  969.                 {
  970.                     int hi=(dat&0xf0)>>4;
  971.                     int     lo=(dat&0xf);
  972.                     patbrk=(hi*10)+lo;
  973.                 }
  974.                 if(patbrk>64) patbrk=64;        /* <- v0.42 fix */
  975.                 posjmp=3;
  976.                 break;
  977.  
  978.             case UNI_PTEFFECTE:
  979.                 DoEEffects(UniGetByte());
  980.                 break;
  981.  
  982.             case UNI_PTEFFECTF:
  983.                 dat=UniGetByte();
  984.  
  985.                 if(vbtick || patdly2) break;
  986.  
  987.                 if(mp_extspd && dat>=0x20){
  988.                     mp_bpm=dat;
  989.                 }
  990.                 else{
  991.                     if(dat){                        /* <- v0.44 bugfix */
  992.                         mp_sngspd=dat;
  993.                         vbtick=0;
  994.                     }
  995.                 }
  996.                 break;
  997.  
  998.             case UNI_S3MEFFECTD:
  999.                 DoS3MVolSlide(UniGetByte());
  1000.                 break;
  1001.  
  1002.             case UNI_S3MEFFECTE:
  1003.                 DoS3MSlideDn(UniGetByte());
  1004.                 break;
  1005.  
  1006.             case UNI_S3MEFFECTF:
  1007.                 DoS3MSlideUp(UniGetByte());
  1008.                 break;
  1009.  
  1010.             case UNI_S3MEFFECTI:
  1011.                 DoS3MTremor(UniGetByte());
  1012.                 a->ownvol=1;
  1013.                 break;
  1014.  
  1015.             case UNI_S3MEFFECTQ:
  1016.                 DoS3MRetrig(UniGetByte());
  1017.                 break;
  1018.  
  1019.             case UNI_S3MEFFECTA:
  1020.                 DoS3MSpeed(UniGetByte());
  1021.                 break;
  1022.  
  1023.             case UNI_S3MEFFECTT:
  1024.                 DoS3MTempo(UniGetByte());
  1025.                 break;
  1026.  
  1027.             case UNI_XMEFFECTA:
  1028.                 DoXMVolSlide(UniGetByte());
  1029.                 break;
  1030.  
  1031.             case UNI_XMEFFECTG:
  1032.                 globalvolume=UniGetByte();
  1033.                 break;
  1034.  
  1035.             case UNI_XMEFFECTH:
  1036.                 DoXMGlobalSlide(UniGetByte());
  1037.                 break;
  1038.  
  1039.             case UNI_XMEFFECTP:
  1040.                 DoXMPanSlide(UniGetByte());
  1041.                 break;
  1042.  
  1043.             default:
  1044.                 UniSkipOpcode(c);
  1045.                 break;
  1046.         }
  1047.     }
  1048.  
  1049.     if(!a->ownper){
  1050.         a->period=a->tmpperiod;
  1051.     }
  1052.  
  1053.     if(!a->ownvol){
  1054.         a->volume=a->tmpvolume;
  1055.     }
  1056. }
  1057.  
  1058.  
  1059.  
  1060.  
  1061. SWORD InterpolateEnv(SWORD p,ENVPT *a,ENVPT *b)
  1062. {
  1063.     return(Interpolate(p,a->pos,b->pos,a->val,b->val));
  1064. }
  1065.  
  1066.  
  1067. SWORD DoPan(SWORD envpan,SWORD pan)
  1068. {
  1069.     return(pan + (((envpan-128)*(128-abs(pan-128)))/128));
  1070. }
  1071.  
  1072.  
  1073.  
  1074. void StartEnvelope(ENVPR *t,UBYTE flg,UBYTE pts,UBYTE sus,UBYTE beg,UBYTE end,ENVPT *p)
  1075. {
  1076.     t->flg=flg;
  1077.     t->pts=pts;
  1078.     t->sus=sus;
  1079.     t->beg=beg;
  1080.     t->end=end;
  1081.     t->env=p;
  1082.     t->p=0;
  1083.     t->a=0;
  1084.     t->b=1;
  1085. }
  1086.  
  1087.  
  1088.  
  1089. SWORD ProcessEnvelope(ENVPR *t,SWORD v,UBYTE keyon)
  1090. {
  1091.     if(t->flg & EF_ON){
  1092.  
  1093.         /* panning active? -> copy variables */
  1094.  
  1095.         UBYTE a,b;
  1096.         UWORD p;
  1097.  
  1098.         a=t->a;
  1099.         b=t->b;
  1100.         p=t->p;
  1101.  
  1102.         /* compute the envelope value between points a and b */
  1103.  
  1104.         v=InterpolateEnv(p,&t->env[a],&t->env[b]);
  1105.  
  1106.         /* Should we sustain? (sustain flag on, key-on, point a is the sustain
  1107.            point, and the pointer is exactly on point a) */
  1108.  
  1109.         if((t->flg & EF_SUSTAIN) && keyon && a==t->sus && p==t->env[a].pos){
  1110.             /* do nothing */
  1111.         }
  1112.         else{
  1113.             /* don't sustain, so increase pointer. */
  1114.  
  1115.             p++;
  1116.  
  1117.             /* pointer reached point b? */
  1118.  
  1119.             if(p >= t->env[b].pos){
  1120.  
  1121.                 /* shift points a and b */
  1122.  
  1123.                 a=b; b++;
  1124.  
  1125.                 if(t->flg & EF_LOOP){
  1126.                     if(b > t->end){
  1127.                         a=t->beg;
  1128.                         b=a+1;
  1129.                         p=t->env[a].pos;
  1130.                     }
  1131.                 }
  1132.                 else{
  1133.                     if(b >= t->pts){
  1134.                         b--;
  1135.                         p--;
  1136.                     }
  1137.                 }
  1138.             }
  1139.         }
  1140.         t->a=a;
  1141.         t->b=b;
  1142.         t->p=p;
  1143.     }
  1144.     return v;
  1145. }
  1146.  
  1147. /*
  1148. long GetFreq2(long period)
  1149. {
  1150.     float frequency;
  1151.  
  1152.     frequency=8363.0*pow(2,((6*12*16*4.0)-period)/(12*16*4.0));
  1153.     return(floor(frequency));
  1154. }
  1155. */
  1156.  
  1157. long GetFreq2(long period)
  1158. {
  1159.     int okt;
  1160.     long frequency;
  1161.     period=7680-period;
  1162.     okt=period/768;
  1163.     frequency=lintab[period%768];
  1164.     frequency<<=2;
  1165.     return(frequency>>(7-okt));
  1166. }
  1167.  
  1168. void MP_HandleTick(void)
  1169. {
  1170.     int z,t,tr;
  1171.     ULONG tmpvol;
  1172.  
  1173.     if(isfirst){           
  1174.         /* don't handle the very first ticks, this allows the
  1175.            other hardware to settle down so we don't loose any 
  1176.            starting notes
  1177.         */
  1178.         isfirst--;
  1179.         return;
  1180.     }
  1181.  
  1182.     if(forbid) return;      /* don't go any further when forbid is true */
  1183.  
  1184.     if(MP_Ready()) return;
  1185.  
  1186.     if(++vbtick>=mp_sngspd){
  1187.  
  1188.         mp_patpos++;
  1189.         vbtick=0;
  1190.  
  1191.         if(patdly){
  1192.             patdly2=patdly;
  1193.             patdly=0;
  1194.         }
  1195.  
  1196.         if(patdly2){
  1197.  
  1198.             /* patterndelay active */
  1199.  
  1200.             if(--patdly2){
  1201.                 mp_patpos--;    /* so turn back mp_patpos by 1 */
  1202.             }
  1203.         }
  1204.  
  1205.         /* Do we have to get a new patternpointer ?
  1206.            (when mp_patpos reaches 64 or when
  1207.            a patternbreak is active) */
  1208.  
  1209.         if( mp_patpos == numrow ) posjmp=3;
  1210.  
  1211.  
  1212.         if( posjmp ){
  1213.             mp_patpos=patbrk;
  1214.             mp_sngpos+=(posjmp-2);
  1215.             patbrk=posjmp=0;
  1216.             if(mp_sngpos>=pf->numpos){
  1217.                 if(!mp_loop) return;
  1218.                 mp_sngpos=pf->reppos;
  1219.             }
  1220.             if(mp_sngpos<0) mp_sngpos=pf->numpos-1;
  1221.         }
  1222.  
  1223.  
  1224.         if(!patdly2){
  1225.  
  1226.             for(t=0;t<pf->numchn;t++){
  1227.  
  1228.                 tr=pf->patterns[(pf->positions[mp_sngpos]*pf->numchn)+t];
  1229.                 numrow=pf->pattrows[pf->positions[mp_sngpos]];
  1230.  
  1231.                 mp_channel=t;
  1232.                 a=&mp_audio[t];
  1233.                 a->row=(tr<pf->numtrk) ? UniFindRow(pf->tracks[tr],mp_patpos) : NULL;
  1234.  
  1235.                 PlayNote();
  1236.             }
  1237.         }
  1238.     }
  1239.  
  1240.     /* Update effects */
  1241.  
  1242.     for(t=0;t<pf->numchn;t++){
  1243.         mp_channel=t;
  1244.         a=&mp_audio[t];
  1245.         PlayEffects();
  1246.     }
  1247.  
  1248.     for(t=0;t<pf->numchn;t++){
  1249.         INSTRUMENT *i;
  1250.         SAMPLE *s;
  1251.         SWORD envpan,envvol;
  1252.  
  1253.         a=&mp_audio[t];
  1254.         i=a->i;
  1255.         s=a->s;
  1256.  
  1257.         if(i==NULL || s==NULL) continue;
  1258.  
  1259.         if(a->period<40) a->period=40;
  1260.         if(a->period>8000) a->period=8000;
  1261.  
  1262.         if(a->kick){
  1263.             MD_VoicePlay(t,a->handle,a->start,s->length,s->loopstart,s->loopend,s->flags);
  1264.             a->kick=0;
  1265.             a->keyon=1;
  1266.  
  1267.             a->fadevol=32768;
  1268.  
  1269.             StartEnvelope(&a->venv,i->volflg,i->volpts,i->volsus,i->volbeg,i->volend,i->volenv);
  1270.             StartEnvelope(&a->penv,i->panflg,i->panpts,i->pansus,i->panbeg,i->panend,i->panenv);
  1271.         }
  1272.  
  1273.         envvol=ProcessEnvelope(&a->venv,256,a->keyon);
  1274.         envpan=ProcessEnvelope(&a->penv,128,a->keyon);
  1275.  
  1276.         tmpvol=a->fadevol;        /* max 32768 */
  1277.         tmpvol*=envvol;            /* * max 256 */
  1278.         tmpvol*=a->volume;        /* * max 64 */
  1279.         tmpvol/=16384;            /* tmpvol/(256*64) => tmpvol is max 32768 */
  1280.  
  1281.         tmpvol*=globalvolume;    /* * max 64 */
  1282.         tmpvol*=mp_volume;        /* * max 100 */
  1283.         tmpvol/=3276800UL;        /* tmpvol/(64*100*512) => tmpvol is max 64 */
  1284.  
  1285.         MD_VoiceSetVolume(t,tmpvol);
  1286.  
  1287.         if(s->flags& SF_OWNPAN){
  1288.             MD_VoiceSetPanning(t,DoPan(envpan,a->panning));
  1289.         }
  1290.         else{
  1291.             MD_VoiceSetPanning(t,a->panning);
  1292.         }
  1293.  
  1294.         if(pf->flags&UF_LINEAR)
  1295.             MD_VoiceSetFrequency(t,GetFreq2(a->period));
  1296.         else
  1297.             MD_VoiceSetFrequency(t,(3579546UL<<2)/a->period);
  1298.  
  1299.         /*  if key-off, start substracting
  1300.             fadeoutspeed from fadevol: */
  1301.  
  1302.         if(!a->keyon){
  1303.             if(a->fadevol>=i->volfade)
  1304.                 a->fadevol-=i->volfade;
  1305.             else
  1306.                 a->fadevol=0;
  1307.         }
  1308.     }
  1309. }
  1310.  
  1311.  
  1312.  
  1313. void MP_Init(UNIMOD *m)
  1314. {
  1315.     int t;
  1316.  
  1317.     pf=m;
  1318.     reppos=0;
  1319.     repcnt=0;
  1320.     mp_sngpos=0;
  1321.     mp_sngspd=m->initspeed;
  1322.  
  1323.     vbtick=mp_sngspd;
  1324.     patdly=0;
  1325.     patdly2=0;
  1326.     mp_bpm=m->inittempo;
  1327.  
  1328.     forbid=0;
  1329.     mp_patpos=0;
  1330.     posjmp=2;               /* <- make sure the player fetches the first note */
  1331.     patbrk=0;
  1332.  
  1333.     isfirst=2;              /* delay start by 2 ticks */
  1334.  
  1335.     globalvolume=64;        /* reset global volume */
  1336.  
  1337.     /* Make sure the player doesn't start with garbage: */
  1338.  
  1339.     for(t=0;t<pf->numchn;t++){
  1340.         mp_audio[t].kick=0;
  1341.         mp_audio[t].tmpvolume=0;
  1342.         mp_audio[t].retrig=0;
  1343.         mp_audio[t].wavecontrol=0;
  1344.         mp_audio[t].glissando=0;
  1345.         mp_audio[t].soffset=0;
  1346.     }
  1347. }
  1348.  
  1349.  
  1350.  
  1351. int MP_Ready(void)
  1352. {
  1353.     return(mp_sngpos>=pf->numpos);
  1354. }
  1355.  
  1356.  
  1357. void MP_NextPosition(void)
  1358. {
  1359.     forbid=1;
  1360.     posjmp=3;
  1361.     patbrk=0;
  1362.     vbtick=mp_sngspd;
  1363.     forbid=0;
  1364. }
  1365.  
  1366.  
  1367. void MP_PrevPosition(void)
  1368. {
  1369.     forbid=1;
  1370.     posjmp=1;
  1371.     patbrk=0;
  1372.     vbtick=mp_sngspd;
  1373.     forbid=0;
  1374. }
  1375.  
  1376.  
  1377. void MP_SetPosition(UWORD pos)
  1378. {
  1379.     if(pos>=pf->numpos) pos=pf->numpos;
  1380.     forbid=1;
  1381.     posjmp=2;
  1382.     patbrk=0;
  1383.     mp_sngpos=pos;
  1384.     vbtick=mp_sngspd;
  1385.     forbid=0;
  1386. }
  1387.